package com.ecoolex.ying.space.admin.graphql;

import com.alibaba.fastjson.JSON;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.util.Assert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.modularize.api.auth.admin.AdminMemberAuthority;
import com.ecoolex.framework.modularize.api.auth.annotation.AdminAuthoritativeRegister;
import com.ecoolex.framework.modularize.api.service.storage.*;
import com.ecoolex.framework.web.api.graphql2.annotation.*;
import com.ecoolex.ying.space.admin.core.AdminConstant;
import com.ecoolex.ying.space.entity.*;
import com.ecoolex.ying.space.enums.PickGoodsStatus;
import com.ecoolex.ying.space.pojo.*;
import com.ecoolex.ying.space.ws.GoodsService;
import com.ecoolex.ying.space.ws.PickGoodsService;
import com.google.common.collect.Lists;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;

import java.util.List;
import java.util.stream.Collectors;

import static com.ecoolex.framework.web.api.graphql2.annotation.GraphQL2Module.Type.Admin;
import static com.ecoolex.ying.space.admin.graphql.PickGoodsGraphql.AUTH;

@GraphQL2Module(type = Admin, description = "优选商品管理")
@AdminAuthoritativeRegister(parentKey = AdminConstant.AUTH_MODULE_KEY, key = AUTH, name = "优选商品管理")
public class PickGoodsGraphql {
    static final String AUTH = AdminConstant.AUTH_MODULE_KEY + "-PICK-GOODS";
    static final String AUTH_GET = AUTH + "-GET";
    static final String AUTH_QUERY = AUTH + "-QUERY";
    static final String AUTH_ADD = AUTH + "-ADD";
    static final String AUTH_EDIT = AUTH + "-EDIT";
    static final String AUTH_DEL = AUTH + "-DEL";
    static final String AUTH_RELEASE = AUTH + "-RELEASE";

    static final UploadSource IMAGE_UPLOAD_SOURCE = new UploadSource("PickGoods", "Image");
    static final UploadLimit IMAGE_UPLOAD_LIMIT = new UploadLimit(FileSize.MB.byteLength(10), MimeType.IMAGE.commons());

    static final UploadSource DETAIL_UPLOAD_SOURCE = new UploadSource("PickGoods", "DetailImage");
    static final UploadLimit DETAIL_UPLOAD_LIMIT = new UploadLimit(FileSize.MB.byteLength(10), MimeType.IMAGE.commons());

    static final UploadSource SHOPWINDOW_IMAGES_UPLOAD_SOURCE = new UploadSource("PickGoods", "ShopwindowImages");
    static final UploadLimit SHOPWINDOW_IMAGES_UPLOAD_LIMIT = new UploadLimit(FileSize.MB.byteLength(10), MimeType.IMAGE.commons());

    static final UploadSource PRODUCT_IMAGE_UPLOAD_SOURCE = new UploadSource("PickGoodsProduct", "Image");
    static final UploadLimit PRODUCT_IMAGE_UPLOAD_LIMIT = new UploadLimit(FileSize.MB.byteLength(10), MimeType.IMAGE.commons());

    @Reference
    private GoodsService goodsService;
    @Reference
    private PickGoodsService pickGoodsService;
    @Autowired
    private StorageService storageService;

    @TypeField(type = PickGoodsWithBLOBs.class, field = "canEdit", description = "能否编辑")
    public boolean canEdit(@Source PickGoodsWithBLOBs source, AdminMemberAuthority user) {
        return user.auth(AUTH_EDIT);
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "canDel", description = "能否删除")
    public boolean canDel(@Source PickGoodsWithBLOBs source, AdminMemberAuthority user) {
        return user.auth(AUTH_DEL);
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "canOnline", description = "能否上线")
    public boolean canOnline(@Source PickGoodsWithBLOBs source, AdminMemberAuthority user) {
        return PickGoodsStatus.canOnline(source);
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "canOffline", description = "能否下线")
    public boolean canOffline(@Source PickGoodsWithBLOBs source) {
        return PickGoodsStatus.canOffline(source);
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "goods", description = "商品")
    public GoodsWithBLOBs goods(@Source PickGoodsWithBLOBs source) {
        return goodsService.getGoodsById(source.getGoodsId());
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "classify", description = "分类")
    public GoodsClassify classify(@Source PickGoodsWithBLOBs source) {
        return Check.isNull(source.getClassifyId()) ? null : goodsService.getClassifyById(source.getClassifyId());
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "labelList", description = "标签列表")
    public List<GoodsLabel> labelList(@Source PickGoodsWithBLOBs source) {
        return goodsService.queryLabelByPickGoodsId(source.getPickGoodsId());
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "image", description = "图片")
    public StorageInfo image(@Source PickGoodsWithBLOBs source) {
        return storageService.get(source.getImage());
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "shopwindowImages", description = "橱窗图片列表")
    public List<StorageInfo> shopwindowImages(@Source PickGoodsWithBLOBs source) {
        if (Check.notNullOrTrimEmpty(source.getShopwindowImages())) {
            return JSON.parseArray(source.getShopwindowImages(), String.class).stream()
                    .map(storageService::get)
                    .filter(Check::notNull)
                    .collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }


    @TypeField(type = PickGoodsWithBLOBs.class, field = "parameters", description = "参数")
    public PickGoodsParametersDTO parameters(@Source PickGoodsWithBLOBs source) {
        return Check.isNullOrTrimEmpty(source.getParameters()) ? null : JSON.parseObject(source.getParameters(), PickGoodsParametersDTO.class);
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "productList", description = "产品列表")
    public List<PickGoodsProduct> productList(@Source PickGoodsWithBLOBs source, AdminMemberAuthority user) {
        return pickGoodsService.queryProductByPickGoodsId(source.getPickGoodsId());
    }

    @TypeField(type = PickGoodsProduct.class, field = "product", description = "产品")
    public GoodsProduct product(@Source PickGoodsProduct source) {
        return goodsService.getProductById(source.getProductId());
    }

    @TypeField(type = PickGoodsProduct.class, field = "image", description = "产品图片")
    public StorageInfo image(@Source PickGoodsProduct source) {
        return storageService.get(source.getImage());
    }

    @TypeField(type = PickGoodsWithBLOBs.class, field = "channelList", description = "渠道列表")
    public List<PickGoodsChannel> channelList(@Source PickGoodsWithBLOBs source, AdminMemberAuthority user) {
        return pickGoodsService.queryChannelByPickGoodsId(source.getPickGoodsId());
    }

    @QueryField(field = "pickGoods", description = "获取优选商品详情")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_GET, name = "获取优选商品详情")
    public PickGoodsWithBLOBs get(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_GET);
        return pickGoodsService.getPickGoodsById(pickGoodsId);
    }

    @QueryField(field = "pickGoodsList", description = "查询优选商品列表")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_QUERY, name = "查询优选商品列表")
    public Pagination<PickGoodsWithBLOBs> query(@NonNull QueryPickGoodsDTO query, @NonNull Sorting[] sorts, @NonNull Page page, AdminMemberAuthority user) {
        user.assertAuth(AUTH_QUERY);
        return pickGoodsService.queryPickGoods(query, sorts, page);
    }

    @QueryField(field = "pickGoodsProductList", description = "查询优选商品产品列表")
    public List<PickGoodsProduct> pickGoodsProductList(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return pickGoodsService.queryProductByPickGoodsId(pickGoodsId);
        } else {
            return user.notAuthority();
        }
    }

    @QueryField(field = "pickGoodsChannelList", description = "查询优选商品渠道列表")
    public List<PickGoodsChannel> pickGoodsChannelList(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return pickGoodsService.queryChannelByPickGoodsId(pickGoodsId);
        } else {
            return user.notAuthority();
        }
    }

    @MutationField(field = "uploadPickGoodsImage", description = "上传优选商品图片")
    public StorageInfo uploadPickGoodsImage(@NonNull Upload request, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return storageService.upload(request, IMAGE_UPLOAD_SOURCE, IMAGE_UPLOAD_LIMIT);
        } else {
            return user.notAuthority();
        }
    }

    @MutationField(field = "uploadPickGoodsDetailImage", description = "上传优选商品详情图片")
    public StorageInfo uploadGoodsDetailImage(@NonNull Upload request, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return storageService.upload(request, DETAIL_UPLOAD_SOURCE, DETAIL_UPLOAD_LIMIT);
        } else {
            return user.notAuthority();
        }
    }

    @MutationField(field = "uploadPickGoodsShopwindowImages", description = "上传优选商品橱窗图片")
    public StorageInfo uploadPickGoodsShopwindowImages(@NonNull Upload request, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return storageService.upload(request, SHOPWINDOW_IMAGES_UPLOAD_SOURCE, SHOPWINDOW_IMAGES_UPLOAD_LIMIT);
        } else {
            return user.notAuthority();
        }
    }

    @MutationField(field = "uploadPickGoodsProductImage", description = "上传优选商品产品图片")
    public StorageInfo uploadPickGoodsProductImage(@NonNull Upload request, AdminMemberAuthority user) {
        if (user.auth(AUTH_ADD) || user.auth(AUTH_EDIT)) {
            return storageService.upload(request, PRODUCT_IMAGE_UPLOAD_SOURCE, PRODUCT_IMAGE_UPLOAD_LIMIT);
        } else {
            return user.notAuthority();
        }
    }

    @MutationField(field = "addPickGoods", description = "添加优选商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_ADD, name = "添加优选商品")
    public PickGoodsWithBLOBs add(@NonNull Integer goodsId, @NonNull EditPickGoodsDTO add, AdminMemberAuthority user) {
        user.assertAuth(AUTH_ADD);
        Goods goods = goodsService.getGoodsById(goodsId);
        Assert.isTrue(Check.notNull(goods), "商品不存在");
        return pickGoodsService.createPickGoods(goodsId, add, user.userName());
    }

    @MutationField(field = "editPickGoods", description = "编辑优选商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_EDIT, name = "编辑优选商品")
    public boolean edit(@NonNull Integer pickGoodsId, EditPickGoodsDTO edit, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        pickGoodsService.updatePickGoods(pickGoodsId, edit, user.userName());
        return true;
    }

    @MutationField(field = "addPickGoodsProduct", description = "添加优选商品产品")
    public PickGoodsProduct add(@NonNull Integer pickGoodsId, @NonNull Integer productId, @NonNull EditPickGoodsProductDTO add, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        PickGoods goods = pickGoodsService.getPickGoodsById(pickGoodsId);
        Assert.isTrue(Check.notNull(goods), "优选商品不存在");
        return pickGoodsService.createProduct(goods, productId, add, user.userName());
    }

    @MutationField(field = "editPickGoodsProduct", description = "编辑优选商品产品")
    public boolean edit(@NonNull Integer pickProductId, @NonNull EditPickGoodsProductDTO edit, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        pickGoodsService.updateProduct(pickProductId, edit, user.userName());
        return true;
    }

    @MutationField(field = "delPickGoodsProduct", description = "删除优选商品产品")
    public boolean delProduct(@NonNull Integer pickProductId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        PickGoodsProduct record = pickGoodsService.getProductById(pickProductId);
        Assert.isTrue(Check.notNull(record), "优选产品不存在");
        pickGoodsService.deleteProduct(record, user.userName());
        return true;
    }

    @MutationField(field = "addPickGoodsChannel", description = "添加优选商品渠道")
    public PickGoodsChannel add(@NonNull AddPickGoodsChannelDTO add, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        return pickGoodsService.createChannel(add, user.userName());
    }

    @MutationField(field = "editPickGoodsChannel", description = "编辑优选商品渠道")
    public boolean edit(@NonNull EditPickGoodsChannelDTO edit, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        pickGoodsService.updateChannel(edit, user.userName());
        return true;
    }

    @MutationField(field = "delPickGoodsChannel", description = "删除优选商品渠道")
    public boolean delChannel(@NonNull Integer channelId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_EDIT);
        PickGoodsChannel record = pickGoodsService.getChannelById(channelId);
        Assert.isTrue(Check.notNull(record), "渠道不存在");
        pickGoodsService.deleteChannel(record, user.userName());
        return true;
    }

    @MutationField(field = "delPickGoods", description = "删除优选商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_DEL, name = "删除优选商品")
    public boolean del(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_DEL);
        PickGoodsWithBLOBs record = pickGoodsService.getPickGoodsById(pickGoodsId);
        Assert.isTrue(Check.notNull(record), "优选商品不存在");
        pickGoodsService.deletePickGoods(record, user.userName());
        return true;
    }

    @MutationField(field = "onlinePickGoods", description = "上线优选商品")
    @AdminAuthoritativeRegister(parentKey = AUTH, key = AUTH_RELEASE, name = "发布优选商品")
    public boolean online(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_RELEASE);
        PickGoodsWithBLOBs record = pickGoodsService.getPickGoodsById(pickGoodsId);
        Assert.isTrue(Check.notNull(record), "优选商品不存在");
        pickGoodsService.onlinePickGoods(record, user.userName());
        return true;
    }

    @MutationField(field = "offlinePickGoods", description = "下线优选商品")
    public boolean offline(@NonNull Integer pickGoodsId, AdminMemberAuthority user) {
        user.assertAuth(AUTH_RELEASE);
        PickGoodsWithBLOBs record = pickGoodsService.getPickGoodsById(pickGoodsId);
        Assert.isTrue(Check.notNull(record), "优选商品不存在");
        pickGoodsService.offlinePickGoods(record, user.userName());
        return true;
    }
}
